#include "DataManagerSingleton.h"

DataManagerSingleton* DataManagerSingleton::instance = NULL;

DataManagerSingleton::DataManagerSingleton(){
	extractions = NULL;
	fps = 60;
}

int DataManagerSingleton::getFps(){
	return fps;
}

void DataManagerSingleton::initializeMlt(int widgetId){
	m_profile = new Mlt::Profile ("square_ntsc_wide");
	m_consumer = new Mlt::Consumer (*m_profile, "sdl_preview");

	// Embed the SDL window in our GUI.
	m_consumer->set("window_id", widgetId);
	m_consumer->set("play.audio_buffer", 4096);
	QPalette pal;
	m_consumer->set("window_background", pal.color(QPalette::Window).name().toAscii().constData());

	// Load a color producer to clear the video region with black.
	m_producer = new Mlt::Producer(*m_profile, "color:");
	m_consumer->connect(*m_producer);
	m_producer->set_speed(0.0);
	//m_consumer->start(); //HERE
}

void DataManagerSingleton::openVideo(QString fileName){
	cout << "DEBUG :: fileName :" << fileName.toAscii().constData() << endl;
	Mlt::Producer *producer = new Mlt::Producer(*m_profile, fileName.toUtf8().constData());
	//Mlt::Producer *newProducer = new Mlt::Producer(*m_profile, this->inFileName.toUtf8().data());
	this->inFileName = fileName;
	if(producer->is_valid()){
		m_consumer->stop();
		m_consumer->connect(*producer);
		delete m_producer;
		m_producer = producer;
		m_producer->set_speed(0.0);
		//m_consumer->start(); //si je met ca ca marche plus...peut etre qu'il peut y avoir un seul consumer a la fois
		if(extractions != NULL){
			delete extractions;
		}
		extractions = new QList<Extraction>();
		fps = m_producer->get_fps();
	}else{
		cout << "ERROR :: invalid producer :" << endl;
	}
}

void DataManagerSingleton::addExtraction(int position){
	Extraction extraction;
	int fps = 60; //TODO en fait il faudrait que je recupere le vrai fps
	int ecartInSec = 5;
	int ecartInFrame = fps*ecartInSec;
	extraction.start = position - ecartInFrame;
	if(extraction.start < 0){
		extraction.start = 0;
	}
	extraction.end = position + ecartInFrame;
	if(extraction.end > m_producer->get_length()){
		extraction.end = m_producer->get_length();
	}
	extractions->append(extraction);
}

void DataManagerSingleton::removeExtraction(int position){
	//TODO
}

void DataManagerSingleton::play(){
	//cout << "m_producer position play1: " << (int) m_producer->position() << endl;
	m_producer->set_speed(1.0);
	if(m_consumer->is_stopped()){
		//cout << "consumer is stopped" << endl;
		m_consumer->start();
	}
	m_consumer->set("refresh", 1);
	//cout << "m_producer position play2: " << (int) m_producer->position() << endl;
}

void DataManagerSingleton::pause(){
	m_producer->set_speed(0.0);
}

void DataManagerSingleton::stopConsumer(){
	m_consumer->stop();
}

DataManagerSingleton *DataManagerSingleton::getInstance(){
	if(!instance){
		instance = new DataManagerSingleton();
	}
	return instance;
}

Extraction DataManagerSingleton::getExtraction(int indice){
	return extractions->at(indice);
}

void DataManagerSingleton::setExtraction(int indice, Extraction newExtraction){
	extractions->replace(indice, newExtraction);
}

void DataManagerSingleton::changeExtraction(int rowIndex){
	//cout << "changeExtraction called : row index : " << rowIndex << endl;
	Extraction extraction = getExtraction(rowIndex);
	//cout << "extraction.start : " << extraction.start << endl;
	//cout << "m_producer position before: " << (int) m_producer->position() << endl;
	//sleep(0.5);
	m_producer->seek(extraction.start);
	//cout << "m_producer position after: " << (int) m_producer->position() << endl;
	//pause(); //si je met en pause le seek est annule...
}

int DataManagerSingleton::getLengthVideo(){
	return m_producer->get_length();
}

void DataManagerSingleton::seek(int frame){
	m_producer->seek(frame);
}

int DataManagerSingleton::getPosition(){
	return (int)m_producer->position();
}

void DataManagerSingleton::saveExtractions(QString fileName){
	Mlt::Playlist *playlist = new Mlt::Playlist();
	cout << "DEBUG : this->inFileName : " << this->inFileName.toStdString() << endl;
	cout << "DEBUG : fileName : " << fileName.toStdString() << endl;
	Mlt::Producer *newProducer = new Mlt::Producer(*m_profile, this->inFileName.toUtf8().constData());
	//Mlt::Producer *newProducer = new Mlt::Producer(*m_profile, this->inFileName.toUtf8().data());
	playlist->append(*newProducer);

	int nExtractions = extractions->count();
	//foreach(const Extraction &extraction, *extractions){
	int lastLeftFrame = getLengthVideo();
	Extraction extraction;
	cout << "nExtractions : " << nExtractions << endl;
	for(int i=nExtractions-1; i>=0; i--){
		cout << "i : " << i << endl;
		extraction = extractions->at(i);
		cout << extraction.start << "," << extraction.end << endl;
		if(extraction.end < lastLeftFrame){
			cout << "extraction.end < lastLeftFrame true" << endl;
			playlist->remove_region(extraction.end, lastLeftFrame-extraction.end);
			cout << "region removed " << extraction.end << " " << lastLeftFrame-extraction.end << endl;
		}
		lastLeftFrame = extraction.start;
	}
	extraction = extractions->at(0);
	if(extraction.start > 0){
		cout << "extraction.start > 0" << endl;
		playlist->remove_region(0, extraction.start);
		cout << "region remoeved" << endl;
	}
	Mlt::Consumer *outFileConsumer = new Mlt::Consumer (*m_profile, "avformat", fileName.toUtf8().constData());
	outFileConsumer->connect(*playlist);
	outFileConsumer->run();
	std::cout << "Finished" << std::endl;
}

